﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks.Dataflow;
using System.Threading.Tasks;

namespace AsyncCheapPool
{
    public class CheapPool<T>
    {
        private BufferBlock<T> _core = new BufferBlock<T>();

        public void PutInPool(T item)
        {
            _core.Post(item);
        }

        public async Task<ItemToken<T>> GetFromPoolAsync()
        {
            var item = await _core.ReceiveAsync();
            return new ItemToken<T>(item, () => this.PutInPool(item));

        }
        public Task<ItemToken<T>> GetFromPoolAsyncWithoutAwait()
        {
            var item =  _core.ReceiveAsync();
            var rt = item.ContinueWith(
                     task =>
                       new ItemToken<T>(task.Result, () => this.PutInPool(task.Result))
                 );
            return rt;
        }

        public ItemToken<T> GetFromPoolSyncBlocking()
        {
            var item = _core.Receive();
            return new ItemToken<T>(item, () => this.PutInPool(item));
        }

        public bool TryGetFromPoolSync(out ItemToken<T> token )
        {
            T item;
            var got = _core.TryReceive(out item);
            if ( !got)
            {
                token = null;
                return false;
            }

            token = new ItemToken<T>(item, () => this.PutInPool(item));
            return got;
        }
    }

}
